#include "matrix4.h"

matrix4::matrix4()
{
	zero();
}
matrix4::~matrix4()
{
	zero();
}
void matrix4::transpose()
{
	_10 = _01;
	_20 = _02;
	_21 = _12;
	_30 = _03;
	_31 = _13;
	_32 = _23;
}
void matrix4::identity()
{
	zero();
	_00 = _11 = _22 = _33 = 1.0;
}
void matrix4::zero()
{
	_00 = _01 = _02 = _03 = 0.0;
	_10 = _11 = _12 = _13 = 0.0;
	_20 = _21 = _22 = _23 = 0.0;
	_30 = _31 = _32 = _33 = 0.0;
}
double matrix4::det()
{
	return (_00*( _11*_22*_33 + _12*_23*_31 + _13*_21*_32 - _13*_22*_31 - _23*_32*_11 - _33*_12*_21 ) -
			_10*( _01*_22*_33 + _02*_23*_31 + _03*_21*_32 - _03*_22*_31 - _23*_32*_01 - _33*_02*_21) +
			_20*( _01*_12*_33 + _02*_13*_31 + _03*_11*_32 - _03*_12*_31 - _31*_32*_01 - _33*_02*_11) -
			_30*( _01*_12*_23 + _02*_13*_21 + _03*_11*_22 - _03*_12*_21 - _31*_22*_01 - _23*_02*_11) );
}
void  matrix4::rotateByAxisX(double angle)
{
	matrix4 temp;
	temp.identity();
	temp._11 = cos(angle);
	temp._12 = -sin(angle);
	temp._21 = sin(angle);
	temp._22 = cos(angle);
	*this *= temp;

}
void  matrix4::rotateByAxisY(double angle)
{
	matrix4 temp;
	temp.identity();
	temp._00 = cos(angle);
	temp._02 = sin(angle);
	temp._20 = -sin(angle);
	temp._11 = cos(angle);
	*this *= temp;
}
void  matrix4::rotateByAxisZ(double angle)
{
	matrix4 temp;
	temp.identity();
	temp._00 = cos(angle);
	temp._01 = -sin(angle);
	temp._10 = sin(angle);
	temp._22 = cos(angle);
	*this *= temp;
}
matrix4 matrix4::operator+()
{
	matrix4 temp;
	temp._00 = +(this->_00);
	temp._01 = +(this->_01);
	temp._02 = +(this->_02);
	temp._03 = +(this->_03);
	temp._10 = +(this->_10);
	temp._11 = +(this->_11);
	temp._12 = +(this->_12);
	temp._13 = +(this->_13);
	temp._20 = +(this->_20);
	temp._21 = +(this->_21);
	temp._22 = +(this->_22);
	temp._23 = +(this->_23);
	temp._30 = +(this->_30);
	temp._31 = +(this->_31);
	temp._32 = +(this->_32);
	temp._33 = +(this->_33);
	return temp;
}
matrix4 matrix4::operator-()
{
	matrix4 temp;
	temp._00 = -(this->_00);
	temp._01 = -(this->_01);
	temp._02 = -(this->_02);
	temp._03 = -(this->_03);
	temp._10 = -(this->_10);
	temp._11 = -(this->_11);
	temp._12 = -(this->_12);
	temp._13 = -(this->_13);
	temp._20 = -(this->_20);
	temp._21 = -(this->_21);
	temp._22 = -(this->_22);
	temp._23 = -(this->_23);
	temp._30 = -(this->_30);
	temp._31 = -(this->_31);
	temp._32 = -(this->_32);
	temp._33 = -(this->_33);
	return temp;
}
matrix4 matrix4::operator+( matrix4 &other )
{
	matrix4 temp;
	temp._00 += (other._00);
	temp._01 += (other._01);
	temp._02 += (other._02);
	temp._03 += (other._03);
	temp._10 += (other._10);
	temp._11 += (other._11);
	temp._12 += (other._12);
	temp._13 += (other._13);
	temp._20 += (other._20);
	temp._21 += (other._21);
	temp._22 += (other._22);
	temp._23 += (other._23);
	temp._30 += (other._30);
	temp._31 += (other._31);
	temp._32 += (other._32);
	temp._33 += (other._33);
	return temp;
}
matrix4 & matrix4::operator+=(matrix4 &other )
{
	this->_00 += (other._00);
	this->_01 += (other._01);
	this->_02 += (other._02);
	this->_03 += (other._03);
	this->_10 += (other._10);
	this->_11 += (other._11);
	this->_12 += (other._12);
	this->_13 += (other._13);
	this->_20 += (other._20);
	this->_21 += (other._21);
	this->_22 += (other._22);
	this->_23 += (other._23);
	this->_30 += (other._30);
	this->_31 += (other._31);
	this->_32 += (other._32);
	this->_33 += (other._33);
	return *this;
}
matrix4 matrix4::operator-( matrix4 &other )
{
	matrix4 temp;
	temp._00 -= (other._00);
	temp._01 -= (other._01);
	temp._02 -= (other._02);
	temp._03 -= (other._03);
	temp._10 -= (other._10);
	temp._11 -= (other._11);
	temp._12 -= (other._12);
	temp._13 -= (other._13);
	temp._20 -= (other._20);
	temp._21 -= (other._21);
	temp._22 -= (other._22);
	temp._23 -= (other._23);
	temp._30 -= (other._30);
	temp._31 -= (other._31);
	temp._32 -= (other._32);
	temp._33 -= (other._33);
	return temp;
}
matrix4 & matrix4::operator-=( matrix4 &other )
{
	this->_00 -= (other._00);
	this->_01 -= (other._01);
	this->_02 -= (other._02);
	this->_03 -= (other._03);
	this->_10 -= (other._10);
	this->_11 -= (other._11);
	this->_12 -= (other._12);
	this->_13 -= (other._13);
	this->_20 -= (other._20);
	this->_21 -= (other._21);
	this->_22 -= (other._22);
	this->_23 -= (other._23);
	this->_30 -= (other._30);
	this->_31 -= (other._31);
	this->_32 -= (other._32);
	this->_33 -= (other._33);
	return *this;
}
matrix4 matrix4::operator*( matrix4 &other )
{
	matrix4 temp;
	temp._00 = this->_00*other._00 + this->_01*other._10 + this->_02*other._20 + this->_03*other._30;
	temp._01 = this->_00*other._01 + this->_01*other._11 + this->_02*other._21 + this->_03*other._31;
	temp._02 = this->_00*other._02 + this->_01*other._12 + this->_02*other._22 + this->_03*other._32;
	temp._03 = this->_00*other._03 + this->_01*other._13 + this->_02*other._23 + this->_03*other._33;
	temp._10 = this->_10*other._00 + this->_11*other._10 + this->_12*other._20 + this->_13*other._30;
	temp._11 = this->_10*other._01 + this->_11*other._11 + this->_12*other._21 + this->_13*other._31;
	temp._12 = this->_10*other._02 + this->_11*other._12 + this->_12*other._22 + this->_13*other._32;
	temp._13 = this->_10*other._03 + this->_11*other._13 + this->_12*other._23 + this->_13*other._33;
	temp._20 = this->_20*other._00 + this->_21*other._10 + this->_22*other._20 + this->_23*other._30;
	temp._21 = this->_20*other._01 + this->_21*other._11 + this->_22*other._21 + this->_23*other._31;
	temp._22 = this->_20*other._02 + this->_21*other._12 + this->_22*other._22 + this->_23*other._32;
	temp._23 = this->_20*other._03 + this->_21*other._13 + this->_22*other._23 + this->_23*other._33;
	temp._30 = this->_30*other._00 + this->_31*other._10 + this->_32*other._20 + this->_33*other._30;
	temp._31 = this->_30*other._01 + this->_31*other._11 + this->_32*other._21 + this->_33*other._31;
	temp._32 = this->_30*other._02 + this->_31*other._12 + this->_32*other._22 + this->_33*other._32;
	temp._33 = this->_30*other._03 + this->_31*other._13 + this->_32*other._23 + this->_33*other._33;
	return temp;
}
matrix4 matrix4::operator*( double &scalar )
{
	matrix4 temp;
	temp._00 = this->_00 * scalar;
	temp._01 = this->_01 * scalar;
	temp._02 = this->_02 * scalar;
	temp._03 = this->_03 * scalar;
	temp._10 = this->_10 * scalar;
	temp._11 = this->_11 * scalar;
	temp._12 = this->_12 * scalar;
	temp._13 = this->_13 * scalar;
	temp._20 = this->_20 * scalar;
	temp._21 = this->_21 * scalar;
	temp._22 = this->_22 * scalar;
	temp._23 = this->_23 * scalar;
	temp._30 = this->_30 * scalar;
	temp._31 = this->_31 * scalar;
	temp._32 = this->_32 * scalar;
	temp._33 = this->_33 * scalar;
	return temp;	
}
matrix4 matrix4::operator*( float &scalar )
{
	matrix4 temp;
	temp._00 = this->_00 * (double)scalar;
	temp._01 = this->_01 * (double)scalar;
	temp._02 = this->_02 * (double)scalar;
	temp._03 = this->_03 * (double)scalar;
	temp._10 = this->_10 * (double)scalar;
	temp._11 = this->_11 * (double)scalar;
	temp._12 = this->_12 * (double)scalar;
	temp._13 = this->_13 * (double)scalar;
	temp._20 = this->_20 * (double)scalar;
	temp._21 = this->_21 * (double)scalar;
	temp._22 = this->_22 * (double)scalar;
	temp._23 = this->_23 * (double)scalar;
	temp._30 = this->_30 * (double)scalar;
	temp._31 = this->_31 * (double)scalar;
	temp._32 = this->_32 * (double)scalar;
	temp._33 = this->_33 * (double) scalar;
	return temp;
}
matrix4 matrix4::operator*( int &scalar )
{
	matrix4 temp;
	temp._00 = this->_00 * (double)scalar;
	temp._01 = this->_01 * (double)scalar;
	temp._02 = this->_02 * (double)scalar;
	temp._03 = this->_03 * (double)scalar;
	temp._10 = this->_10 * (double)scalar;
	temp._11 = this->_11 * (double)scalar;
	temp._12 = this->_12 * (double)scalar;
	temp._13 = this->_13 * (double)scalar;
	temp._20 = this->_20 * (double)scalar;
	temp._21 = this->_21 * (double)scalar;
	temp._22 = this->_22 * (double)scalar;
	temp._23 = this->_23 * (double)scalar;
	temp._30 = this->_30 * (double)scalar;
	temp._31 = this->_31 * (double)scalar;
	temp._32 = this->_32 * (double)scalar;
	temp._33 = this->_33 * (double)scalar;
	return temp;
}
matrix4 & matrix4::operator*=( matrix4 &other )
{
	matrix4 temp;
	temp._00 = this->_00*other._00 + this->_01*other._10 + this->_02*other._20 + this->_03*other._30;
	temp._01 = this->_00*other._01 + this->_01*other._11 + this->_02*other._21 + this->_03*other._31;
	temp._02 = this->_00*other._02 + this->_01*other._12 + this->_02*other._22 + this->_03*other._32;
	temp._03 = this->_00*other._03 + this->_01*other._13 + this->_02*other._23 + this->_03*other._33;
	temp._10 = this->_10*other._00 + this->_11*other._10 + this->_12*other._20 + this->_13*other._30;
	temp._11 = this->_10*other._01 + this->_11*other._11 + this->_12*other._21 + this->_13*other._31;
	temp._12 = this->_10*other._02 + this->_11*other._12 + this->_12*other._22 + this->_13*other._32;
	temp._13 = this->_10*other._03 + this->_11*other._13 + this->_12*other._23 + this->_13*other._33;
	temp._20 = this->_20*other._00 + this->_21*other._10 + this->_22*other._20 + this->_23*other._30;
	temp._21 = this->_20*other._01 + this->_21*other._11 + this->_22*other._21 + this->_23*other._31;
	temp._22 = this->_20*other._02 + this->_21*other._12 + this->_22*other._22 + this->_23*other._32;
	temp._23 = this->_20*other._03 + this->_21*other._13 + this->_22*other._23 + this->_23*other._33;
	temp._30 = this->_30*other._00 + this->_31*other._10 + this->_32*other._20 + this->_33*other._30;
	temp._31 = this->_30*other._01 + this->_31*other._11 + this->_32*other._21 + this->_33*other._31;
	temp._32 = this->_30*other._02 + this->_31*other._12 + this->_32*other._22 + this->_33*other._32;
	temp._33 = this->_30*other._03 + this->_31*other._13 + this->_32*other._23 + this->_33*other._33;
	*this = temp;
	return *this;
}
matrix4 & matrix4::operator*=( double &scalar )
{
	this->_00 *= scalar;
	this->_01 *= scalar;
	this->_02 *= scalar;
	this->_03 *= scalar;
	this->_10 *= scalar;
	this->_11 *= scalar;
	this->_12 *= scalar;
	this->_13 *= scalar;
	this->_20 *= scalar;
	this->_21 *= scalar;
	this->_22 *= scalar;
	this->_23 *= scalar;
	this->_30 *= scalar;
	this->_31 *= scalar;
	this->_32 *= scalar;
	this->_33 *= scalar;
	return *this;
}
matrix4 & matrix4::operator*=( float &scalar )
{
	this->_00 *= (double)scalar;
	this->_01 *= (double)scalar;
	this->_02 *= (double)scalar;
	this->_03 *= (double)scalar;
	this->_10 *= (double)scalar;
	this->_11 *= (double)scalar;
	this->_12 *= (double)scalar;
	this->_13 *= (double)scalar;
	this->_20 *= (double)scalar;
	this->_21 *= (double)scalar;
	this->_22 *= (double)scalar;
	this->_23 *= (double)scalar;
	this->_30 *= (double)scalar;
	this->_31 *= (double)scalar;
	this->_32 *= (double)scalar;
	this->_33 *= (double)scalar;
	return *this;
}
matrix4 & matrix4::operator*=( int &scalar )
{
	this->_00 *= (double)scalar;
	this->_01 *= (double)scalar;
	this->_02 *= (double)scalar;
	this->_03 *= (double)scalar;
	this->_10 *= (double)scalar;
	this->_11 *= (double)scalar;
	this->_12 *= (double)scalar;
	this->_13 *= (double)scalar;
	this->_20 *= (double)scalar;
	this->_21 *= (double)scalar;
	this->_22 *= (double)scalar;
	this->_23 *= (double)scalar;
	this->_30 *= (double)scalar;
	this->_31 *= (double)scalar;
	this->_32 *= (double)scalar;
	this->_33 *= (double)scalar;
	return *this;
}
matrix4 matrix4::operator/( double &scalar )
{
	matrix4 temp;
	temp._00 = this->_00 / scalar;
	temp._01 = this->_01 / scalar;
	temp._02 = this->_02 / scalar;
	temp._03 = this->_03 / scalar;
	temp._10 = this->_10 / scalar;
	temp._11 = this->_11 / scalar;
	temp._12 = this->_12 / scalar;
	temp._13 = this->_13 / scalar;
	temp._20 = this->_20 / scalar;
	temp._21 = this->_21 / scalar;
	temp._22 = this->_22 / scalar;
	temp._23 = this->_23 / scalar;
	temp._30 = this->_30 / scalar;
	temp._31 = this->_31 / scalar;
	temp._32 = this->_32 / scalar;
	temp._33 = this->_33 / scalar;
	return temp;
}
matrix4 matrix4::operator/( float &scalar )
{
	matrix4 temp;
	temp._00 = this->_00 / (double)scalar;
	temp._01 = this->_01 / (double)scalar;
	temp._02 = this->_02 / (double)scalar;
	temp._03 = this->_03 / (double)scalar;
	temp._10 = this->_10 / (double)scalar;
	temp._11 = this->_11 / (double)scalar;
	temp._12 = this->_12 / (double)scalar;
	temp._13 = this->_13 / (double)scalar;
	temp._20 = this->_20 / (double)scalar;
	temp._21 = this->_21 / (double)scalar;
	temp._22 = this->_22 / (double)scalar;
	temp._23 = this->_23 / (double)scalar;
	temp._30 = this->_30 / (double)scalar;
	temp._31 = this->_31 / (double)scalar;
	temp._32 = this->_32 / (double)scalar;
	temp._33 = this->_33 / (double)scalar;
	return temp;
}
matrix4 matrix4::operator/( int &scalar )
{
	matrix4 temp;
	temp._00 = this->_00 / (double)scalar;
	temp._01 = this->_01 / (double)scalar;
	temp._02 = this->_02 / (double)scalar;
	temp._03 = this->_03 / (double)scalar;
	temp._10 = this->_10 / (double)scalar;
	temp._11 = this->_11 / (double)scalar;
	temp._12 = this->_12 / (double)scalar;
	temp._13 = this->_13 / (double)scalar;
	temp._20 = this->_20 / (double)scalar;
	temp._21 = this->_21 / (double)scalar;
	temp._22 = this->_22 / (double)scalar;
	temp._23 = this->_23 / (double)scalar;
	temp._30 = this->_30 / (double)scalar;
	temp._31 = this->_31 / (double)scalar;
	temp._32 = this->_32 / (double)scalar;
	temp._33 = this->_33 / (double)scalar;
	return temp;
}
matrix4 & matrix4::operator/=( double &scalar )
{
	this->_00 /= scalar;
	this->_01 /= scalar;
	this->_02 /= scalar;
	this->_03 /= scalar;
	this->_10 /= scalar;
	this->_11 /= scalar;
	this->_12 /= scalar;
	this->_13 /= scalar;
	this->_20 /= scalar;
	this->_21 /= scalar;
	this->_22 /= scalar;
	this->_23 /= scalar;
	this->_30 /= scalar;
	this->_31 /= scalar;
	this->_32 /= scalar;
	this->_33 /= scalar;
	return *this;
}
matrix4 & matrix4::operator/=( float &scalar )
{
	this->_00 /= (double)scalar;
	this->_01 /= (double)scalar;
	this->_02 /= (double)scalar;
	this->_03 /= (double)scalar;
	this->_10 /= (double)scalar;
	this->_11 /= (double)scalar;
	this->_12 /= (double)scalar;
	this->_13 /= (double)scalar;
	this->_20 /= (double)scalar;
	this->_21 /= (double)scalar;
	this->_22 /= (double)scalar;
	this->_23 /= (double)scalar;
	this->_30 /= (double)scalar;
	this->_31 /= (double)scalar;
	this->_32 /= (double)scalar;
	this->_33 /= (double)scalar;
	return *this;
}
matrix4 & matrix4::operator/=( int &scalar )
{
	this->_00 /= (double)scalar;
	this->_01 /= (double)scalar;
	this->_02 /= (double)scalar;
	this->_03 /= (double)scalar;
	this->_10 /= (double)scalar;
	this->_11 /= (double)scalar;
	this->_12 /= (double)scalar;
	this->_13 /= (double)scalar;
	this->_20 /= (double)scalar;
	this->_21 /= (double)scalar;
	this->_22 /= (double)scalar;
	this->_23 /= (double)scalar;
	this->_30 /= (double)scalar;
	this->_31 /= (double)scalar;
	this->_32 /= (double)scalar;
	this->_33 /= (double)scalar;
	return *this;
}
matrix4 & matrix4::operator=( matrix4 &other )
{
	this->_00 = other._00;
	this->_01 = other._01;
	this->_02 = other._02;
	this->_03 = other._03;
	this->_10 = other._10;
	this->_11 = other._11;
	this->_12 = other._12;
	this->_13 = other._13;
	this->_20 = other._20;
	this->_21 = other._21;
	this->_22 = other._22;
	this->_23 = other._23;
	this->_30 = other._30;
	this->_31 = other._31;
	this->_32 = other._32;
	this->_33 = other._33;
	return *this;
}
bool matrix4::operator==(matrix4 &other)
{
	bool equal(true);
	if( this->_00 != other._00)
		equal = false;
	if( this->_01 != other._01)
		equal = false;
	if( this->_02 != other._02)
		equal = false;
	if( this->_03 != other._03)
		equal = false;
	if( this->_10 != other._10)
		equal = false;
	if( this->_11 != other._11)
		equal = false;
	if( this->_12 != other._12)
		equal = false;
	if( this->_13 != other._13)
		equal = false;
	if( this->_20 != other._20)
		equal = false;
	if( this->_21 != other._21)
		equal = false;
	if( this->_22 != other._22)
		equal = false;
	if( this->_23 != other._23)
		equal = false;
	if( this->_30 != other._30)
		equal = false;
	if( this->_31 != other._31)
		equal = false;
	if( this->_32 != other._32)
		equal = false;
	if( this->_33 != other._33)
		equal = false;
	return equal;
}
bool matrix4::operator!=(matrix4 &other)
{
	bool notEqual(true);
	if( this->_00 == other._00)
		notEqual = false;
	if( this->_01 == other._01)
		notEqual = false;
	if( this->_02 == other._02)
		notEqual = false;
	if( this->_03 == other._03)
		notEqual = false;
	if( this->_10 == other._10)
		notEqual = false;
	if( this->_11 == other._11)
		notEqual = false;
	if( this->_12 == other._12)
		notEqual = false;
	if( this->_13 == other._13)
		notEqual = false;
	if( this->_20 == other._20)
		notEqual = false;
	if( this->_21 == other._21)
		notEqual = false;
	if( this->_22 == other._22)
		notEqual = false;
	if( this->_23 == other._23)
		notEqual = false;
	if( this->_30 == other._30)
		notEqual = false;
	if( this->_31 == other._31)
		notEqual = false;
	if( this->_32 == other._32)
		notEqual = false;
	if( this->_33 == other._33)
		notEqual = false;
	return notEqual;
}